﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace thnger.ZmotionEcl1408Pro
{
    public class Zmotion
    {
        public Zmotion(string IPAddress = "127.0.0.1")
        {
            this.IPAddress = IPAddress;
        }

        private string IPAddress = string.Empty;

        private IntPtr Handle;

        public bool InitedOK;

        public int unit0 = 400; //脉冲当量
        public int unit1 = 400; //脉冲当量
        public int unit2 = 400; //脉冲当量
        public int unit3 = 400; //脉冲当量


        /// <summary>
        /// 搜索IP地址结合
        /// </summary>
        /// <returns></returns>
        public List<string> GetEhList()
        {
            StringBuilder ipAddressList = new StringBuilder(100);

            uint addbufferlength = 1000;

            int error = zmcaux.ZAux_SearchEthlist(ipAddressList, addbufferlength, 10);

            if (error == 0)
            {
                string result = ipAddressList.ToString().Trim();

                if (result.Contains(' '))
                {
                    return result.Split(' ').ToList();
                }
                else
                {
                    return new List<string>() { result };
                }
            }
            return new List<string>();
        }


        /// <summary>
        /// 初始化板卡
        /// </summary>
        /// <returns></returns>
        public OperationResult InitCard()
        {
            int error = zmcaux.ZAux_OpenEth(this.IPAddress, out Handle);

            if (error == 0 && Handle != IntPtr.Zero)
            {
                InitedOK = true;
                return OperationResult.CreateSuccessResult();
            }
            else
            {
                InitedOK = false;
                return OperationResult.CreateFailResult();
            }

        }

        /// <summary>
        /// 关闭板卡
        /// </summary>
        /// <returns></returns>
        public OperationResult CloseCard()
        {
            if (zmcaux.ZAux_Close(Handle) == 0)
            {
                Handle = IntPtr.Zero;
                InitedOK = false;
                return OperationResult.CreateSuccessResult();
            }
            return OperationResult.CreateFailResult();
        }

        /// <summary>
        /// 连续运动
        /// </summary>
        /// <param name="axis">轴号</param>
        /// <param name="vel">运行速度</param>
        /// <param name="dir">方向</param>
        /// <param name="velMin">最小速度</param>
        /// <param name="acc">加速度</param>
        /// <param name="dec">减速带</param>
        /// <param name="sramp">S曲线时间</param>
        /// <returns>操作结果</returns>
        public OperationResult VMove(short axis, float vel, bool dir, float velMin, float acc, float dec, float sramp)
        {
            //判断是否满足运动条件
            var result = CommonMotionValidate(axis);

            if(!result.IsSuccess)return result;

            //创建错误码
            int error = 0;

            try
            {

                //设置轴类型

                /*
                Atype类型 描述
                0 虚拟轴。
                1 脉冲方向方式的步进或伺服 。
                2 模拟信号控制方式的伺服 。
                3 正交编码器 。
                4 步进 + 编码器 。
                6 脉冲方向方式的编码器，可用于手轮输入。
                7 脉冲方向方式步进或伺服 + EZ信号输入。
                8 ZCAN扩展脉冲方向方式步进或伺服 。
                9 ZCAN扩展正交编码器。
                10 ZCAN扩展脉冲方向方式的编码器
                */
                error = zmcaux.ZAux_Direct_SetAtype(Handle, axis, 1);
                ErrorHandle("ZAux_Direct_SetAtype", error);

                //设置脉冲当量
                switch(axis)
                {
                    case 0:
                        error = zmcaux.ZAux_Direct_SetUnits(Handle, axis, unit0);
                        ErrorHandle("ZAux_Direct_SetUnit", error);
                        break;
                    case 1:
                        error = zmcaux.ZAux_Direct_SetUnits(Handle, axis, unit1);
                        ErrorHandle("ZAux_Direct_SetUnit", error);
                        break;
                    case 2:
                        error = zmcaux.ZAux_Direct_SetUnits(Handle, axis, unit2);
                        ErrorHandle("ZAux_Direct_SetUnit", error);
                        break;
                    case 3:
                        error = zmcaux.ZAux_Direct_SetUnits(Handle, axis, unit3);
                        ErrorHandle("ZAux_Direct_SetUnit", error);
                        break;
                    default:
                        break;
                }

                //设置最小速度
                error = zmcaux.ZAux_Direct_SetLspeed(Handle, axis, velMin);
                ErrorHandle("ZAux_Direct_SetLspeed", error);

                //设置运行速度
                error = zmcaux.ZAux_Direct_SetSpeed(Handle, axis, vel);
                ErrorHandle("ZAux_Direct_SetSpeed", error);

                //设置加速度
                error = zmcaux.ZAux_Direct_SetAccel(Handle, axis, acc);
                ErrorHandle("ZAux_Direct_SetAcceel", error);

                //设置减速度
                error = zmcaux.ZAux_Direct_SetDecel(Handle, axis, dec);
                ErrorHandle("ZAux_Direct_SetDecel", error);

                //设置S曲线时间
                error = zmcaux.ZAux_Direct_SetSramp(Handle, axis, sramp);
                ErrorHandle("ZAux_Direct_SetSramp", error);

                //设置方向并运动
                error = zmcaux.ZAux_Direct_Single_Vmove(Handle,axis, dir ? 1:-1);
                ErrorHandle("ZAux_Direct_Single_Vmove", error);

            }
            catch (Exception ex)
            {
                result.IsSuccess = false;
                result.ErrorMsg = ex.Message;
                return result;
            }
            return OperationResult.CreateSuccessResult();
        }

        /// <summary>
        /// 相对运动
        /// </summary>
        /// <param name="axis"></param>
        /// <param name="vel"></param>
        /// <param name="distance"></param>
        /// <param name="velMin"></param>
        /// <param name="acc"></param>
        /// <param name="dec"></param>
        /// <param name="sramp"></param>
        /// <returns></returns>
        public OperationResult MoveRelative(short axis, float vel, float distance, float velMin, float acc, float dec, float sramp)
        {
            //判断是否满足运动条件
            var result = CommonMotionValidate(axis);

            if (!result.IsSuccess) return result;

            //创建错误码
            int error = 0;

            try
            {

                //设置轴类型

                /*
                Atype类型 描述
                0 虚拟轴。
                1 脉冲方向方式的步进或伺服 。
                2 模拟信号控制方式的伺服 。
                3 正交编码器 。
                4 步进 + 编码器 。
                6 脉冲方向方式的编码器，可用于手轮输入。
                7 脉冲方向方式步进或伺服 + EZ信号输入。
                8 ZCAN扩展脉冲方向方式步进或伺服 。
                9 ZCAN扩展正交编码器。
                10 ZCAN扩展脉冲方向方式的编码器
                */
                error = zmcaux.ZAux_Direct_SetAtype(Handle, axis, 1);
                ErrorHandle("ZAux_Direct_SetAtype", error);

                //设置脉冲当量
                switch (axis)
                {
                    case 0:
                        error = zmcaux.ZAux_Direct_SetUnits(Handle, axis, unit0);
                        ErrorHandle("ZAux_Direct_SetUnit", error);
                        break;
                    case 1:
                        error = zmcaux.ZAux_Direct_SetUnits(Handle, axis, unit1);
                        ErrorHandle("ZAux_Direct_SetUnit", error);
                        break;
                    case 2:
                        error = zmcaux.ZAux_Direct_SetUnits(Handle, axis, unit2);
                        ErrorHandle("ZAux_Direct_SetUnit", error);
                        break;
                    case 3:
                        error = zmcaux.ZAux_Direct_SetUnits(Handle, axis, unit3);
                        ErrorHandle("ZAux_Direct_SetUnit", error);
                        break;
                    default:
                        break;
                }

                //设置最小速度
                error = zmcaux.ZAux_Direct_SetLspeed(Handle, axis, velMin);
                ErrorHandle("ZAux_Direct_SetLspeed", error);

                //设置运行速度
                error = zmcaux.ZAux_Direct_SetSpeed(Handle, axis, vel);
                ErrorHandle("ZAux_Direct_SetSpeed", error);

                //设置加速度
                error = zmcaux.ZAux_Direct_SetAccel(Handle, axis, acc);
                ErrorHandle("ZAux_Direct_SetAcceel", error);

                //设置减速度
                error = zmcaux.ZAux_Direct_SetDecel(Handle, axis, dec);
                ErrorHandle("ZAux_Direct_SetDecel", error);

                //设置S曲线时间
                error = zmcaux.ZAux_Direct_SetSramp(Handle, axis, sramp);
                ErrorHandle("ZAux_Direct_SetSramp", error);

                //设置方向并运动
                error = zmcaux.ZAux_Direct_Single_Move(Handle, axis, distance);
                ErrorHandle("ZAux_Direct_Single_Move", error);

            }
            catch (Exception ex)
            {
                result.IsSuccess = false;
                result.ErrorMsg = ex.Message;
                return result;
            }
            return OperationResult.CreateSuccessResult();
        }

        /// <summary>
        /// 绝对运动
        /// </summary>
        /// <param name="axis"></param>
        /// <param name="vel"></param>
        /// <param name="pos"></param>
        /// <param name="velMin"></param>
        /// <param name="acc"></param>
        /// <param name="dec"></param>
        /// <param name="sramp"></param>
        /// <returns></returns>
        public OperationResult MoveAbs(short axis, float vel, float pos, float velMin, float acc, float dec, float sramp)
        {
            //判断是否满足运动条件
            var result = CommonMotionValidate(axis);

            if (!result.IsSuccess) return result;

            //创建错误码
            int error = 0;

            try
            {

                //设置轴类型

                /*
                Atype类型 描述
                0 虚拟轴。
                1 脉冲方向方式的步进或伺服 。
                2 模拟信号控制方式的伺服 。
                3 正交编码器 。
                4 步进 + 编码器 。
                6 脉冲方向方式的编码器，可用于手轮输入。
                7 脉冲方向方式步进或伺服 + EZ信号输入。
                8 ZCAN扩展脉冲方向方式步进或伺服 。
                9 ZCAN扩展正交编码器。
                10 ZCAN扩展脉冲方向方式的编码器
                */
                error = zmcaux.ZAux_Direct_SetAtype(Handle, axis, 1);
                ErrorHandle("ZAux_Direct_SetAtype", error);

                //设置脉冲当量
                switch (axis)
                {
                    case 0:
                        error = zmcaux.ZAux_Direct_SetUnits(Handle, axis, unit0);
                        ErrorHandle("ZAux_Direct_SetUnit", error);
                        break;
                    case 1:
                        error = zmcaux.ZAux_Direct_SetUnits(Handle, axis, unit1);
                        ErrorHandle("ZAux_Direct_SetUnit", error);
                        break;
                    case 2:
                        error = zmcaux.ZAux_Direct_SetUnits(Handle, axis, unit2);
                        ErrorHandle("ZAux_Direct_SetUnit", error);
                        break;
                    case 3:
                        error = zmcaux.ZAux_Direct_SetUnits(Handle, axis, unit3);
                        ErrorHandle("ZAux_Direct_SetUnit", error);
                        break;
                    default:
                        break;
                }

                //设置最小速度
                error = zmcaux.ZAux_Direct_SetLspeed(Handle, axis, velMin);
                ErrorHandle("ZAux_Direct_SetLspeed", error);

                //设置运行速度
                error = zmcaux.ZAux_Direct_SetSpeed(Handle, axis, vel);
                ErrorHandle("ZAux_Direct_SetSpeed", error);

                //设置加速度
                error = zmcaux.ZAux_Direct_SetAccel(Handle, axis, acc);
                ErrorHandle("ZAux_Direct_SetAcceel", error);

                //设置减速度
                error = zmcaux.ZAux_Direct_SetDecel(Handle, axis, dec);
                ErrorHandle("ZAux_Direct_SetDecel", error);

                //设置S曲线时间
                error = zmcaux.ZAux_Direct_SetSramp(Handle, axis, sramp);
                ErrorHandle("ZAux_Direct_SetSramp", error);

                //设置方向并运动
                error = zmcaux.ZAux_Direct_Single_MoveAbs(Handle, axis, pos);
                ErrorHandle("ZAux_Direct_Single_MoveAbs", error);

            }
            catch (Exception ex)
            {
                result.IsSuccess = false;
                result.ErrorMsg = ex.Message;
                return result;
            }
            return OperationResult.CreateSuccessResult();
        }

        /// <summary>
        /// 2轴相对定位
        /// </summary>
        /// <param name="axis"></param>
        /// <param name="vel"></param>
        /// <param name="distance"></param>
        /// <param name="velMin"></param>
        /// <param name="acc"></param>
        /// <param name="dec"></param>
        /// <param name="sramp"></param>
        /// <returns></returns>
        public OperationResult Move2DReletive(short[] axis, float[] vel, float[] distance, float[]velMin, float[] acc, float[] dec, float[]sramp)
        {
           if(axis.Length == 2 && vel.Length ==2 && distance.Length == 2 && velMin.Length == 2 && dec.Length == 2 && sramp.Length == 2)
            {
                OperationResult result = new OperationResult();

                //相对定位
                for (int i=0;i<2;i++)
                {
                    result = MoveRelative(axis[i], vel[i], distance[i], velMin[i], acc[i], dec[i], sramp[i]);
                    
                    if (!result.IsSuccess) return result;
                }

                //等待停止
                for (int i = 0; i < 2; i++)
                {
                    result = WaitStop(axis[i]);
                    if (!result.IsSuccess) return result;
                }

                return OperationResult.CreateSuccessResult();

            }
            return new OperationResult()
            {
                IsSuccess = false,
                ErrorMsg = "传递参数长度不正确"
            };
        }

        /// <summary>
        /// 2轴绝对定位
        /// </summary>
        /// <param name="axis"></param>
        /// <param name="vel"></param>
        /// <param name="pos"></param>
        /// <param name="velMin"></param>
        /// <param name="acc"></param>
        /// <param name="dec"></param>
        /// <param name="sramp"></param>
        /// <returns></returns>
        public OperationResult Move2DAbs(short[] axis, float[] vel, float[] pos, float[] velMin, float[] acc, float[] dec, float[] sramp)
        {
            if (axis.Length == 2 && vel.Length == 2 && pos.Length == 2 && velMin.Length == 2 && dec.Length == 2 && sramp.Length == 2)
            {
                OperationResult result = new OperationResult();

                //相对定位
                for (int i = 0; i < 2; i++)
                {
                    result = MoveAbs(axis[i], vel[i], pos[i], velMin[i], acc[i], dec[i], sramp[i]);

                    if (!result.IsSuccess) return result;
                }

                //等待停止
                for (int i = 0; i < 2; i++)
                {
                    result = WaitStop(axis[i]);
                    if (!result.IsSuccess) return result;
                }

                return OperationResult.CreateSuccessResult();

            }
            return new OperationResult()
            {
                IsSuccess = false,
                ErrorMsg = "传递参数长度不正确"
            };
        }

        /// <summary>
        /// 3轴相对定位
        /// </summary>
        /// <param name="axis"></param>
        /// <param name="vel"></param>
        /// <param name="distance"></param>
        /// <param name="velMin"></param>
        /// <param name="acc"></param>
        /// <param name="dec"></param>
        /// <param name="sramp"></param>
        /// <returns></returns>
        public OperationResult Move3DReletive(short[] axis, float[] vel, float[] distance, float[] velMin, float[] acc, float[] dec, float[] sramp)
        {
            if (axis.Length == 3 && vel.Length == 3 && distance.Length == 3 && velMin.Length == 3 && dec.Length == 3 && sramp.Length == 3)
            {
                OperationResult result = new OperationResult();

                //2轴定位
                result = Move2DReletive(new short[] { axis[0], axis[1] }, new float[] { vel[0], vel[1] }, new float[] { distance[0], distance[1] }, new float[] { velMin[0], velMin[1] }, new float[] { acc[0], acc[1] }, new float[] { dec[0], dec[1] }, new float[] { sramp[0], sramp[1] });

                result = MoveRelative(axis[2], vel[2], distance[2], velMin[2], acc[2], dec[2], sramp[2]);
                if (!result.IsSuccess) return result;

                //等待停止
                result = WaitStop(axis[2]);
                if (!result.IsSuccess) return result;

                return OperationResult.CreateSuccessResult();

            }
            return new OperationResult()
            {
                IsSuccess = false,
                ErrorMsg = "传递参数长度不正确"
            };
        }

        /// <summary>
        /// 3轴绝对定位
        /// </summary>
        /// <param name="axis"></param>
        /// <param name="vel"></param>
        /// <param name="pos"></param>
        /// <param name="velMin"></param>
        /// <param name="acc"></param>
        /// <param name="dec"></param>
        /// <param name="sramp"></param>
        /// <returns></returns>
        public OperationResult Move3DAbs(short[] axis, float[] vel, float[] pos, float[] velMin, float[] acc, float[] dec, float[] sramp)
        {
            if (axis.Length == 3 && vel.Length == 3 && pos.Length == 3 && velMin.Length == 3 && dec.Length == 3 && sramp.Length == 3)
            {
                OperationResult result = new OperationResult();

                //先动z轴
                result = MoveAbs(axis[2], vel[2], 0.0f, velMin[2], acc[2], dec[2], sramp[2]);
                if (!result.IsSuccess) return result;

                //等待停止
                result = WaitStop(axis[2]);
                if (!result.IsSuccess) return result;

                //2轴定位
                result = Move2DAbs(new short[] { axis[0], axis[1] }, new float[] { vel[0], vel[1] }, new float[] { pos[0], pos[1] }, new float[] { velMin[0], velMin[1] }, new float[] { acc[0], acc[1] }, new float[] { dec[0], dec[1] }, new float[] { sramp[0], sramp[1] });

                result = MoveAbs(axis[2], vel[2], pos[2], velMin[2], acc[2], dec[2], sramp[2]);
                if (!result.IsSuccess) return result;

                //等待停止
                result = WaitStop(axis[2]);
                if (!result.IsSuccess) return result;

                return OperationResult.CreateSuccessResult();

            }
            return new OperationResult()
            {
                IsSuccess = false,
                ErrorMsg = "传递参数长度不正确"
            };
        }

        /// <summary>
        /// 多轴相对直线插补
        /// </summary>
        /// <param name="axis"></param>
        /// <param name="distance"></param>
        /// <param name="vel"></param>
        /// <param name="acc"></param>
        /// <param name="dec"></param>
        /// <returns></returns>
        public OperationResult MoveLineRelative(int[]axis, float[]distance, float vel, float acc, float dec)
        {
            if (axis.Length >= 2 && axis.Length == distance.Length)
            {
                OperationResult result = new OperationResult();

                //判断每个轴是否满足要求
                foreach (var item in axis)
                {
                    result = CommonMotionValidate((short)item);
                    if (!result.IsSuccess) return result;
                }

                int error = 0;
                try
                {
                    //选择BASE轴列表
                    error = zmcaux.ZAux_Direct_Base(Handle, axis.Length, axis);
                    ErrorHandle("ZAux_Direct_Base", error);

                    error = zmcaux.ZAux_Direct_SetSpeed(Handle, axis[0], vel);
                    ErrorHandle("ZAux_Direct_SetSpeed", error);

                    error = zmcaux.ZAux_Direct_SetAccel(Handle, axis[0], acc);
                    ErrorHandle("ZAux_Direct_SetAccel", error);

                    error = zmcaux.ZAux_Direct_SetDecel(Handle, axis[0], dec);
                    ErrorHandle("ZAux_Direct_SetDecel", error);

                    error = zmcaux.ZAux_Direct_Move(Handle, axis.Length, axis, distance);
                    ErrorHandle("ZAux_Direct_Move", error);

                    return OperationResult.CreateSuccessResult();

                }
                catch (Exception ex)
                {
                    result.IsSuccess = false;
                    result.ErrorMsg = ex.Message;
                    return result;
                }
            }
            return new OperationResult()
            {
                IsSuccess = false,
                ErrorMsg = "传递参数不正确"
            };
        }

        /// <summary>
        /// 多轴绝对直线插补
        /// </summary>
        /// <param name="axis"></param>
        /// <param name="distance"></param>
        /// <param name="vel"></param>
        /// <param name="acc"></param>
        /// <param name="dec"></param>
        /// <returns></returns>
        public OperationResult MoveLineAbs(int[] axis, float[] pos, float vel, float acc, float dec)
        {
            if (axis.Length >= 2 && axis.Length == pos.Length)
            {
                OperationResult result = new OperationResult();

                //判断每个轴是否满足要求
                foreach (var item in axis)
                {
                    result = CommonMotionValidate((short)item);
                    if (!result.IsSuccess) return result;
                }

                int error = 0;
                try
                {
                    //选择BASE轴列表
                    error = zmcaux.ZAux_Direct_Base(Handle, axis.Length, axis);
                    ErrorHandle("ZAux_Direct_Base", error);

                    error = zmcaux.ZAux_Direct_SetSpeed(Handle, axis[0], vel);
                    ErrorHandle("ZAux_Direct_SetSpeed", error);

                    error = zmcaux.ZAux_Direct_SetAccel(Handle, axis[0], acc);
                    ErrorHandle("ZAux_Direct_SetAccel", error);

                    error = zmcaux.ZAux_Direct_SetDecel(Handle, axis[0], dec);
                    ErrorHandle("ZAux_Direct_SetDecel", error);

                    error = zmcaux.ZAux_Direct_MoveAbs(Handle, axis.Length, axis, pos);
                    ErrorHandle("ZAux_Direct_MoveAbs", error);

                    return OperationResult.CreateSuccessResult();

                }
                catch (Exception ex)
                {
                    result.IsSuccess = false;
                    result.ErrorMsg = ex.Message;
                    return result;
                }
            }
            return new OperationResult()
            {
                IsSuccess = false,
                ErrorMsg = "传递参数不正确"
            };
        }

        /// <summary>
        /// XY圆弧相对插补(圆心定位)
        /// </summary>
        /// <param name="axis"></param>
        /// <param name="distance"></param>
        /// <param name="circlecenter"></param>
        /// <param name="vel"></param>
        /// <param name="acc"></param>
        /// <param name="dec"></param>
        /// <param name="dir"></param>
        /// <returns></returns>
        public OperationResult MoveCircleRelative(int[] axis, float[] distance, float[]circlecenter, float vel, float acc, float dec, int dir)
        {
            if (axis.Length == 2 && axis.Length == distance.Length)
            {
                OperationResult result = new OperationResult();

                //判断每个轴是否满足要求
                foreach (var item in axis)
                {
                    result = CommonMotionValidate((short)item);
                    if (!result.IsSuccess) return result;
                }

                int error = 0;
                try
                {
                    //选择BASE轴列表
                    error = zmcaux.ZAux_Direct_Base(Handle, axis.Length, axis);
                    ErrorHandle("ZAux_Direct_Base", error);

                    error = zmcaux.ZAux_Direct_SetSpeed(Handle, axis[0], vel);
                    ErrorHandle("ZAux_Direct_SetSpeed", error);

                    error = zmcaux.ZAux_Direct_SetAccel(Handle, axis[0], acc);
                    ErrorHandle("ZAux_Direct_SetAccel", error);

                    error = zmcaux.ZAux_Direct_SetDecel(Handle, axis[0], dec);
                    ErrorHandle("ZAux_Direct_SetDecel", error);

                    error = zmcaux.ZAux_Direct_MoveCirc(Handle, axis.Length, axis, distance[0], distance[1], circlecenter[0], circlecenter[1],dir);
                    ErrorHandle("ZAux_Direct_MoveCirc", error);

                    return OperationResult.CreateSuccessResult();

                }
                catch (Exception ex)
                {
                    result.IsSuccess = false;
                    result.ErrorMsg = ex.Message;
                    return result;
                }
            }
            return new OperationResult()
            {
                IsSuccess = false,
                ErrorMsg = "传递参数不正确"
            };
        }

        /// <summary>
        /// XY圆弧绝对插补(圆心定位)
        /// </summary>
        /// <param name="axis"></param>
        /// <param name="distance"></param>
        /// <param name="circlecenter"></param>
        /// <param name="vel"></param>
        /// <param name="acc"></param>
        /// <param name="dec"></param>
        /// <param name="dir"></param>
        /// <returns></returns>
        public OperationResult MoveCircleAbs(int[] axis, float[] distance, float[] circlecenter, float vel, float acc, float dec, int dir)
        {
            if (axis.Length == 2 && axis.Length == distance.Length)
            {
                OperationResult result = new OperationResult();

                //判断每个轴是否满足要求
                foreach (var item in axis)
                {
                    result = CommonMotionValidate((short)item);
                    if (!result.IsSuccess) return result;
                }

                int error = 0;
                try
                {
                    //选择BASE轴列表
                    error = zmcaux.ZAux_Direct_Base(Handle, axis.Length, axis);
                    ErrorHandle("ZAux_Direct_Base", error);

                    error = zmcaux.ZAux_Direct_SetSpeed(Handle, axis[0], vel);
                    ErrorHandle("ZAux_Direct_SetSpeed", error);

                    error = zmcaux.ZAux_Direct_SetAccel(Handle, axis[0], acc);
                    ErrorHandle("ZAux_Direct_SetAccel", error);

                    error = zmcaux.ZAux_Direct_SetDecel(Handle, axis[0], dec);
                    ErrorHandle("ZAux_Direct_SetDecel", error);

                    error = zmcaux.ZAux_Direct_MoveCircAbs(Handle, axis.Length, axis, distance[0], distance[1], circlecenter[0], circlecenter[1], dir);
                    ErrorHandle("ZAux_Direct_MoveCircAbs", error);

                    return OperationResult.CreateSuccessResult();

                }
                catch (Exception ex)
                {
                    result.IsSuccess = false;
                    result.ErrorMsg = ex.Message;
                    return result;
                }
            }
            return new OperationResult()
            {
                IsSuccess = false,
                ErrorMsg = "传递参数不正确"
            };
        }

        /// <summary>
        /// XY圆弧相对插补(中点定位)
        /// </summary>
        /// <param name="axis"></param>
        /// <param name="distance"></param>
        /// <param name="midpos"></param>
        /// <param name="vel"></param>
        /// <param name="acc"></param>
        /// <param name="dec"></param>
        /// <param name="dir"></param>
        /// <returns></returns>
        public OperationResult MoveCircle2Relative(int[] axis, float[] distance, float[] midpos, float vel, float acc, float dec)
        {
            if (axis.Length == 2 && axis.Length == distance.Length)
            {
                OperationResult result = new OperationResult();

                //判断每个轴是否满足要求
                foreach (var item in axis)
                {
                    result = CommonMotionValidate((short)item);
                    if (!result.IsSuccess) return result;
                }

                int error = 0;
                try
                {
                    //选择BASE轴列表
                    error = zmcaux.ZAux_Direct_Base(Handle, axis.Length, axis);
                    ErrorHandle("ZAux_Direct_Base", error);

                    error = zmcaux.ZAux_Direct_SetSpeed(Handle, axis[0], vel);
                    ErrorHandle("ZAux_Direct_SetSpeed", error);

                    error = zmcaux.ZAux_Direct_SetAccel(Handle, axis[0], acc);
                    ErrorHandle("ZAux_Direct_SetAccel", error);

                    error = zmcaux.ZAux_Direct_SetDecel(Handle, axis[0], dec);
                    ErrorHandle("ZAux_Direct_SetDecel", error);

                    error = zmcaux.ZAux_Direct_MoveCirc2(Handle, axis.Length, axis, midpos[0], midpos[1], distance[0], distance[1]);
                    ErrorHandle("ZAux_Direct_MoveCirc2", error);

                    return OperationResult.CreateSuccessResult();

                }
                catch (Exception ex)
                {
                    result.IsSuccess = false;
                    result.ErrorMsg = ex.Message;
                    return result;
                }
            }
            return new OperationResult()
            {
                IsSuccess = false,
                ErrorMsg = "传递参数不正确"
            };
        }

        /// <summary>
        /// XY圆弧绝对插补(中点定位)
        /// </summary>
        /// <param name="axis"></param>
        /// <param name="distance"></param>
        /// <param name="midpos"></param>
        /// <param name="vel"></param>
        /// <param name="acc"></param>
        /// <param name="dec"></param>
        /// <param name="dir"></param>
        /// <returns></returns>
        public OperationResult MoveCircle2Abs(int[] axis, float[] distance, float[] midpos, float vel, float acc, float dec)
        {
            if (axis.Length == 2 && axis.Length == distance.Length)
            {
                OperationResult result = new OperationResult();

                //判断每个轴是否满足要求
                foreach (var item in axis)
                {
                    result = CommonMotionValidate((short)item);
                    if (!result.IsSuccess) return result;
                }

                int error = 0;
                try
                {
                    //选择BASE轴列表
                    error = zmcaux.ZAux_Direct_Base(Handle, axis.Length, axis);
                    ErrorHandle("ZAux_Direct_Base", error);

                    error = zmcaux.ZAux_Direct_SetSpeed(Handle, axis[0], vel);
                    ErrorHandle("ZAux_Direct_SetSpeed", error);

                    error = zmcaux.ZAux_Direct_SetAccel(Handle, axis[0], acc);
                    ErrorHandle("ZAux_Direct_SetAccel", error);

                    error = zmcaux.ZAux_Direct_SetDecel(Handle, axis[0], dec);
                    ErrorHandle("ZAux_Direct_SetDecel", error);

                    error = zmcaux.ZAux_Direct_MoveCirc2Abs(Handle, axis.Length, axis, midpos[0], midpos[1], distance[0], distance[1]);
                    ErrorHandle("ZAux_Direct_MoveCirc2Abs", error);

                    return OperationResult.CreateSuccessResult();

                }
                catch (Exception ex)
                {
                    result.IsSuccess = false;
                    result.ErrorMsg = ex.Message;
                    return result;
                }
            }
            return new OperationResult()
            {
                IsSuccess = false,
                ErrorMsg = "传递参数不正确"
            };
        }

        /// <summary>
        /// 通用回零操作
        /// </summary>
        /// <param name="axis">轴号</param>
        /// <param name="vel">速度</param>
        /// <param name="creep">爬行速度</param>
        /// <param name="homeio">原点IO</param>
        /// <param name="distance">原限位距离</param>
        /// <param name="velMin">最小速度</param>
        /// <param name="acc">加速度</param>
        /// <param name="dec">减速带</param>
        /// <param name="sramp">S曲线时间</param>
        /// <param name="homemode">回零模式</param>
        /// <returns></returns>
        public OperationResult ZeroAxis(short axis, float vel, float creep, int homeio, float distance, float velMin, float acc, float dec, float sramp, int homemode = 4)
        {
            //判断是否满足运动条件
            var result = CommonMotionValidate(axis);

            if (!result.IsSuccess) return result;

            //先往原点方向一直走，直到到达限位
            result = MoveRelative(axis, vel, -500, velMin, acc, dec, sramp);
            if (!result.IsSuccess) return result;

            //等待停止
            result = WaitStop(axis);
            if (!result.IsSuccess) return result;

            //位置清零
            result = ZeroPos(axis);
            if (!result.IsSuccess) return result;


            //往反方向走一段距离，超过原点和限位的距离
            result = MoveRelative(axis, vel, distance, velMin, acc, dec, sramp);
            if (!result.IsSuccess) return result;

            //等待停止
            result = WaitStop(axis);
            if (!result.IsSuccess) return result;

            //直接回零
            result = DirectZeroAxis(axis, vel, creep, homeio, velMin, acc, dec, homemode);
            if (!result.IsSuccess) return result;

            //等待回零停止
            result = WaitHomeStop(axis);
            if (!result.IsSuccess) return result;

            //返回成功
            return OperationResult.CreateSuccessResult();

        }

        /// <summary>
        /// 直接回原点
        /// </summary>
        /// <param name="axis">轴号</param>
        /// <param name="vel">速度</param>
        /// <param name="creep">爬行速度</param>
        /// <param name="homeio">原点IO点</param>
        /// <param name="velMin">最小速度</param>
        /// <param name="acc">加速度</param>
        /// <param name="dec">减速带</param>
        /// <param name="homemode">回零模式</param>
        /// <returns></returns>
        public OperationResult DirectZeroAxis(short axis, float vel, float creep, int homeio, float velMin, float acc, float dec, int homemode = 4)
        {
            //判断是否满足运动条件
            var result = CommonMotionValidate(axis);

            if (!result.IsSuccess) return result;

            //创建错误码
            int error = 0;

            try
            {
                //设置轴类型
                error = zmcaux.ZAux_Direct_SetAtype(Handle, axis, 1);
                ErrorHandle("ZAux_Direct_SetAtype", error);

                //设置脉冲当量
                switch (axis)
                {
                    case 0:
                        error = zmcaux.ZAux_Direct_SetUnits(Handle, axis, unit0);
                        ErrorHandle("ZAux_Direct_SetUnit", error);
                        break;
                    case 1:
                        error = zmcaux.ZAux_Direct_SetUnits(Handle, axis, unit1);
                        ErrorHandle("ZAux_Direct_SetUnit", error);
                        break;
                    case 2:
                        error = zmcaux.ZAux_Direct_SetUnits(Handle, axis, unit2);
                        ErrorHandle("ZAux_Direct_SetUnit", error);
                        break;
                    case 3:
                        error = zmcaux.ZAux_Direct_SetUnits(Handle, axis, unit3);
                        ErrorHandle("ZAux_Direct_SetUnit", error);
                        break;
                    default:
                        break;
                }

                //设置最小速度
                error = zmcaux.ZAux_Direct_SetLspeed(Handle, axis, velMin);
                ErrorHandle("ZAux_Direct_SetLspeed", error);

                //设置运行速度
                error = zmcaux.ZAux_Direct_SetSpeed(Handle, axis, vel);
                ErrorHandle("ZAux_Direct_SetSpeed", error);

                //设置加速度
                error = zmcaux.ZAux_Direct_SetAccel(Handle, axis, acc);
                ErrorHandle("ZAux_Direct_SetAcceel", error);

                //设置减速度
                error = zmcaux.ZAux_Direct_SetDecel(Handle, axis, dec);
                ErrorHandle("ZAux_Direct_SetDecel", error);

                //设置爬行速度
                error = zmcaux.ZAux_Direct_SetCreep(Handle, axis, creep);
                ErrorHandle("ZAux_Direct_SetCreep", error);

                //设置HomeIO
                error = zmcaux.ZAux_Direct_SetDatumIn(Handle, axis, homeio);
                ErrorHandle("ZAux_Direct_SetDatumIn", error);

                //执行回原点
                error = zmcaux.ZAux_Direct_Single_Datum(Handle, axis, homemode);
                ErrorHandle("ZAux_Direct_Single_Datum", error);

            }
            catch (Exception ex)
            {
                result.IsSuccess = false;
                result.ErrorMsg = ex.Message;
                return result;
            }
            return OperationResult.CreateSuccessResult();
        }

        /// <summary>
        /// 等待停止
        /// </summary>
        /// <param name="axis">轴号</param>
        /// <returns></returns>
        /// 
        public OperationResult WaitStop(short axis)
        {
            //判断是否满足运动条件
            var result = CommonInitedValidate();

            if (!result.IsSuccess) return result;

            //创建错误码
            int error = 0;

            int runstate = 0;

            do
            {
                error = zmcaux.ZAux_Direct_GetIfIdle(Handle, axis, ref runstate);

                ErrorHandle("ZAux_Direct_GetIfIdle", error);

            } while (runstate == 0);

            return OperationResult.CreateSuccessResult();
        }


        /// <summary>
        /// 等待回零停止
        /// </summary>
        /// <param name="axis">轴号</param>
        /// <returns></returns>
        public OperationResult WaitHomeStop(short axis)
        {
            //判断是否满足运动条件
            var result = CommonInitedValidate();

            if (!result.IsSuccess) return result;

            //创建错误码
            int error = 0;

            uint homestate = 0;

            do
            {
                error = zmcaux.ZAux_Direct_GetHomeStatus(Handle, axis, ref homestate);

                ErrorHandle("ZAux_Direct_GetHomeStatus", error);

            } while (homestate == 0);

            return OperationResult.CreateSuccessResult();
        }


        /// <summary>
        /// 停止轴
        /// </summary>
        /// <param name="axis">轴号</param>
        /// <returns>操作结果</returns>
        public OperationResult StopAxis(short axis)
        {
            var result = CommonInitedValidate();

            if (!result.IsSuccess) return result;

            //错误码
            int error = 0;

            try
            {
                /*
                 模式：
                    0 （缺省）取消当前运动
                    1 取消缓冲的运动
                    2 取消当前运动和缓冲运动
                    3 立即中断脉冲发送
                 */

                error = zmcaux.ZAux_Direct_Single_Cancel(Handle, axis, 2);
                ErrorHandle("ZAux_Direct_Single_Cancel", error);    
            }
            catch (Exception ex)
            {
                result.IsSuccess = false;
                result.ErrorMsg = ex.Message;
                return result;
            }
            return OperationResult.CreateSuccessResult();
        }

        /// <summary>
        /// 停止所有轴
        /// </summary>
        /// <returns></returns>
        public OperationResult StopAllAxis()
        {
            var result = CommonInitedValidate();

            if (!result.IsSuccess) return result;

            //错误码
            int error = 0;

            try
            {
                /*
                 模式：
                    0 取消当前运动
                    1 取消缓冲的运动
                    2 取消当前运动和缓冲运动
                    3 立即停止
                 */

                error = zmcaux.ZAux_Direct_CancelAxisList(Handle, 4, new int[]{0,1,2,3}, 3);
                ErrorHandle("ZAux_Direct_CancelAxisList", error);
            }
            catch (Exception ex)
            {
                result.IsSuccess = false;
                result.ErrorMsg = ex.Message;
                return result;
            }
            return OperationResult.CreateSuccessResult();
        }



        /// <summary>
        /// 获取实时速度
        /// </summary>
        /// <param name="axis"></param>
        /// <returns></returns>
        public float GetVel(short axis)
        {
            //判断是否满足初始化条件
            var result = CommonInitedValidate();

            if (!result.IsSuccess) return 0.0f;

            //定义速度
            float vel = 0.0f;

            //定义错误码
            int error = 0;

            try
            {
                error = zmcaux.ZAux_Direct_GetVpSpeed(Handle, axis, ref vel);

                ErrorHandle("ZAux_Direct_GetVpSpeed", error);

                return vel;
            }
            catch (Exception)
            {
                return 0.0f;
            }
        }

        /// <summary>
        /// 获取实时位置
        /// </summary>
        /// <param name="axis"></param>
        /// <returns></returns>
        public float GetPos(short axis)
        {
            //判断是否满足初始化条件
            var result = CommonInitedValidate();

            if (!result.IsSuccess) return 0.0f;

            //定义位置
            float pos = 0.0f;

            //定义错误码
            int error = 0;

            try
            {
                error = zmcaux.ZAux_Direct_GetMpos(Handle, axis, ref pos);

                ErrorHandle("ZAux_Direct_GetMpos", error);

                return pos;
            }
            catch (Exception)
            {
                return 0.0f;
            }
        }

        /// <summary>
        /// 单轴运动位置清零
        /// </summary>
        /// <param name="axis"></param>
        /// <returns></returns>
        public OperationResult ZeroPos(short axis)
        {
            //判断是否满足初始化条件
            var result = CommonInitedValidate();

            if (!result.IsSuccess) return result;

            //定义错误码
            int error = 0;

            try
            {
                error = zmcaux.ZAux_Direct_SetMpos(Handle, axis, 0.0f);

                ErrorHandle("ZAux_Direct_SetMpos", error);
            }
            catch (Exception ex)
            {
                result.IsSuccess = false;
                result.ErrorMsg = ex.Message;
                return result;
            }
            return OperationResult.CreateSuccessResult();
        }


        /// <summary>
        /// 通用运动验证
        /// </summary>
        /// <param name="axis"></param>
        /// <returns></returns>
        private OperationResult CommonMotionValidate(short axis)
        {
            OperationResult result = CommonInitedValidate();
            //判断是否已经初始化
            if (!result.IsSuccess) return result;

            //判断是否正在运行
            if (IsMoving(axis))
                {
                result.IsSuccess = false;
                result.ErrorMsg = "轴正在运行中";
                return result;
            }
            return OperationResult.CreateSuccessResult();
        }

        /// <summary>
        /// 通用初始化验证
        /// </summary>
        /// <returns></returns>
        private OperationResult CommonInitedValidate()
        {
            OperationResult result = new OperationResult();
            //判断是否已经初始化
            if (!InitedOK)
            {
                result.IsSuccess = false;
                result.ErrorMsg = "控制器未初始化";
                return result;
            }
            else
            {
                return OperationResult.CreateSuccessResult();
            }
        }

        /// <summary>
        /// 错误处理
        /// </summary>
        /// <param name="command">执行命令</param>
        /// <param name="error"></param>
        private void ErrorHandle(string command, int error)
        {
            string result = string.Empty;
            switch (error)
            {
                case 0: break;
                default:
                    result = string.Format("{0}" + "指令执行错误，错误码为{1}", command, error);
                    break;
            }
        }

        /// <summary>
        /// 判断某个轴是否正在运行
        /// </summary>
        /// <param name="axis"></param>
        /// <returns></returns>
        public bool IsMoving(short axis)
        {
            OperationResult result = CommonInitedValidate();

            //判断是否已经初始化
            if (!result.IsSuccess) return false;

            //定义运行状态
            int runstate = -1;

            //定义错误码
            int error = 0;

            try
            {
                //获取轴状态
                error = zmcaux.ZAux_Direct_GetIfIdle(Handle, axis, ref runstate);

                //错误码验证
                ErrorHandle("ZAux_Direct_GetIfIdle", error);

                return runstate == 0;
            }
            catch (Exception)
            {
                return true;

            }

        }

        /// <summary>
        /// 操作结果类
        /// </summary>
        public class OperationResult
        {
            /// <summary>
            /// 是否成功
            /// </summary>
            public bool IsSuccess { get; set; }

            /// <summary>
            /// 错误信息
            /// </summary>
            public string ErrorMsg { get; set; }

            public static OperationResult CreateSuccessResult()
            {
                return new OperationResult()
                {
                    IsSuccess = true,
                    ErrorMsg = "Success"
                };
            }

            public static OperationResult CreateFailResult()
            {
                return new OperationResult()
                {
                    IsSuccess = false,
                    ErrorMsg = "Fail"
                };
            }
        }
      
    }
} 
